﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using MiscUtil;

namespace TlvLib
{
    public class Server
    {
        private readonly int _port;
        private TcpListener _tcpListener;
        private bool _started;
        private Timer _timer;

        public event Action<PacketHandler> NewConnectionEstablished;

        public Action<string> UiLogger { get; set; }

        public void OnNewConnectionEstablished(PacketHandler packetHandler)
        {
            Action<PacketHandler> handler = NewConnectionEstablished;
            if (handler != null) handler(packetHandler);
        }

        public Server(int port)
        {
            _port = port;
            _timer = new Timer(o => this.Start(), null, -1, -1);
        }

        public void Start()
        {
            _tcpListener = new TcpListener(IPAddress.Any, _port);

            try
            {
                var msg = string.Format("开始监听端口{0}", _port);
                LogToUi(msg);
                _tcpListener.Start(5);
            }
            catch (SocketException ex)
            {
                var msg = string.Format("监听端口发生异常，程序无法正常运行，请确认端口{0}未被占用，或者只有一个程序实例在运行。", _port);
                LogToUi(msg);
                Restart();
                return;
            }

            AcceptClient();

        }

        public void Stop()
        {
            CloseSocket();
        }

        private void AcceptClient()
        {
            try
            {
                _tcpListener.BeginAcceptTcpClient(AcceptCallback, _tcpListener);
            }
            catch (SocketException)
            {
                Restart();
                return;
            }
            catch (ObjectDisposedException)
            {
            }
        }

        private void CloseSocket()
        {
            if (_tcpListener != null)
            {
                _tcpListener.Stop();
            }
        }

        private void Restart()
        {
            CloseSocket();
            _timer.Change(10000, -1);

        }

        private void AcceptCallback(IAsyncResult ar)
        {
            var tcpListener = (TcpListener)ar.AsyncState;
            try
            {
                var tcpClient = tcpListener.EndAcceptTcpClient(ar);
                var msg = string.Format("收到连接来自：{0}", tcpClient.Client.RemoteEndPoint);
                LogToUi(msg);

                var reader = new PacketReader(tcpClient);
                var handler = new PacketHandler(reader);
                handler.SetLogger(UiLogger);

                OnNewConnectionEstablished(handler);

                reader.Start();
                reader.StatusReport += ReaderOnStatusReport;

            }
            catch (ObjectDisposedException)
            {
                return;
            }
            catch (SocketException)
            {

            }


            AcceptClient();
        }

        private void ReaderOnStatusReport(object sender, EventArgs<string> args)
        {
            LogToUi(args.Value);
        }

        private void LogToUi(string message)
        {
            var logger = this.UiLogger;
            if (logger != null)
            {
                logger(message);
            }
        }
    }


}
